Skip to content

feat: Add docs for DownloadHandler #4309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: latest
Choose a base branch
from
Open

Conversation

mshabarov
Copy link
Contributor

Adds a documentation for new API for handling downloads in Vaadin 24.8.

Fixes #4303

Copy link

github-actions bot commented May 14, 2025

AI Language Review

Comment on lines +315 to +341
== Using Custom Servlet and Request Parameters

You can create a custom servlet which handles "image" as a relative URL:

[source,java]
----
@WebServlet(urlPatterns = "/image", name = "DynamicContentServlet")
public class DynamicContentServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("image/svg+xml");
String name = req.getParameter("name");
if (name == null) {
name = "";
}
String svg = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
+ "<svg xmlns='http://www.w3.org/2000/svg' "
+ "xmlns:xlink='http://www.w3.org/1999/xlink'>"
+ "<rect x='10' y='10' height='100' width='100' "
+ "style=' fill: #90C3D4'/><text x='30' y='30' fill='red'>"
+ name + "</text>" + "</svg>";
resp.getWriter().write(svg);
}
}
----
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is from the old article, I'd keep it just in case if someone is interested in a low level servlet way of downloading a content.

@mshabarov mshabarov requested review from Copilot and caalador May 14, 2025 13:45
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds comprehensive documentation for the new DownloadHandler API in Vaadin 24.8, including multiple usage scenarios and API customization examples.

  • Removed the legacy dynamic content documentation.
  • Added detailed documentation for DownloadHandler covering classpath resource downloads, file system downloads, dynamic InputStream downloads, progress tracking, and custom download handlers.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
articles/flow/advanced/dynamic-content.adoc Legacy documentation removed.
articles/flow/advanced/downloads.adoc New documentation added for the DownloadHandler API.
Comments suppressed due to low confidence (1)

articles/flow/advanced/downloads.adoc:241

  • [nitpick] The class name 'LinkWithM5Validation' is ambiguous; consider renaming it to something more descriptive, such as 'LinkWithChecksumValidation'.
private static class LinkWithM5Validation extends Anchor {

Comment on lines +215 to +218
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] digest = md5.digest(data);
String base64Md5 = Base64.getEncoder().encodeToString(digest);
event.getResponse().setHeader("Content-MD5", base64Md5);
Copy link
Contributor Author

@mshabarov mshabarov May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example with calculating MD5 checksum and checking it on the client isn't perhaps a realistic case. I'd think of a better case for when setting a header is useful in download handler, feel free to share a better example if you have any.


* You can use a [classname]`DownloadHandler`, which handles HTTP requests automatically.
* You can build a custom URL using [classname]`String` type parameters.
In this case, you need one more servlet, which handles the URL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't push people to have an extra servlet for dynamic content generation.
The custom URL feels like it shouldn't be in the downloads document (even if it was from the old documentation)
At the minimum this should have a link to == Using Custom Servlet and Request Parameters

The [classname]`DownloadHandler` API provides a flexible high-level abstraction to implement file and arbitrary contents downloads from server to browser in Vaadin applications.
This API supports various download scenarios, from simple file downloads to complex streaming with progress tracking.

Downloading is supported by multiple different Vaadin components such as `Anchor`, `Image`, `IFrame`, `Avatar`, `AvatarGroup`, `SvgIcon`, `MessageListItem`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not list any components specifically and only mention that Vaadin Components support DownloadHandler where applicable.

This API supports various download scenarios, from simple file downloads to complex streaming with progress tracking.

Downloading is supported by multiple different Vaadin components such as `Anchor`, `Image`, `IFrame`, `Avatar`, `AvatarGroup`, `SvgIcon`, `MessageListItem`.
Note that "download" here doesn't refer to only downloading a file to the user's file system, but it also covers cases where an HTML element downloads a file into the browser's cache and renders it from there, e.g. `Image` component.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Note that "download" here doesn't refer to only downloading a file to the user's file system, but it also covers cases where an HTML element downloads a file into the browser's cache and renders it from there, e.g. `Image` component.
[NOTE]
"download" doesn't refer to only downloading a file to the user's file system, but it also covers cases where an HTML element transfers data into the browser's cache and renders it, e.g. `Image` component.

Comment on lines +28 to +33
This documentation covers the main features of the `DownloadHandler` API, including:

* Static helper methods for common download scenarios
* Download progress tracking
* Creating custom download handlers
* Low-level API features
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be direct links to the respective parts of the document


The `DownloadHandler` API provides several static helper methods to simplify common download scenarios.

=== Download A Classpath Resource
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
=== Download A Classpath Resource
=== Download a Classpath Resource

I think it doesn't want A Classpath , but a Classpath instead.

* `ONLY_WHEN_ENABLED`: Download handling is rejected when the owner component is disabled (default)
* `ALWAYS`: Download handling is allowed even when the owner component is disabled

[classname]`DownloadHandler` allows to override this mode by overriding the `getDisabledUpdateMode()` method.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[classname]`DownloadHandler` allows to override this mode by overriding the `getDisabledUpdateMode()` method.
[classname]`DownloadHandler` allows to override this mode by overriding the [methodname]`getDisabledUpdateMode()` method.

The `inert` property controls whether the download should be handled when the owner component is in an inert state, e.g. when a modal dialog is opened while the owner component is on the underlined page.
See the <<../advanced/server-side-modality.adoc#,Server-Side Modality>> for details.

[classname]`DownloadHandler` allows to handle download request from inert component by overriding the `allowInert()` method.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[classname]`DownloadHandler` allows to handle download request from inert component by overriding the `allowInert()` method.
[classname]`DownloadHandler` allows to handle download request from inert component by overriding the [methodname]`allowInert()` method.


=== URL Postfix

The `getUrlPostfix()` method allows you to specify an optional URL postfix that appends application-controlled string, e.g. the logical name of the target file, to the end of the otherwise random-looking download URL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `getUrlPostfix()` method allows you to specify an optional URL postfix that appends application-controlled string, e.g. the logical name of the target file, to the end of the otherwise random-looking download URL.
The [methodname]`getUrlPostfix()` method allows you to specify an optional URL postfix that appends application-controlled string, e.g. the logical name of the target file, to the end of the otherwise random-looking download URL.


You can create a custom servlet which handles "image" as a relative URL:

[source,java]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have a sample with the new DownloadHandler for the exact same case to see difference between the approaches.

* `onComplete(TransferContext, long)`: Called when the download completes with the total transferred bytes
* `progressReportInterval()`: Defines how often progress updates are sent (in bytes)

The [classname]`TransferContext` provides information about the download, such as the file name, content length (if known), a reference to an owner component and Vaadin request, response and session.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TransferProgressListener example for Customized DownloadHandler as the reading from stream you should do is not apparent from the text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Documentation for the new Download API
2 participants